using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using System.Reflection;

namespace WiMo.Games.GameEngine.WP7S.XNA
{
    public class GameEngine : Game, IGameEngine
    {
        private GraphicsDeviceManager _graphics;

        public bool EnableDiagnostics{ get; set;}
        public bool IsPaused { get; set; }
        public Color DiagnosticsFontColor { get; set; }
        public PointF DiagnosticsLocation { get; set; }
        public ISpriteFont DefaultFont { get; set; }
        public new List<IGameComponent> Components { get; set; }
        public IDisplay Display { get; set; }
        public IAssetFactory AssetFactory { get; set; }
        public IGame Game { get; private set; }
        public IAudioManager AudioManager { get; set; }
        public WiMo.Games.Inputs.IInputManager InputManager {get; set;}
        public IContentManager ContentManager { get; set; }
        public ICollisionManager CollisionManager { get; set; }
        public IPhysicsManager PhysicsManager { get; set; }
        public IStateManager StateManager { get; set; }
        public WiMo.Games.Menus.IMenuManager MenuManager { get; set; }
        public Random Randomizer { get; private set; }

        public object GraphicsManager
        {
            get { return GraphicsDevice; }
        }

        public GameEngine()
        {
            _graphics = new GraphicsDeviceManager(this);
            _graphics.SupportedOrientations = DisplayOrientation.Portrait;
            _graphics.PreferredBackBufferWidth = 480;
            _graphics.PreferredBackBufferHeight = 800;

            AssetFactory = new AssetFactory(this, this.Content);
            ContentManager = new ContentManager(this, this.Content);
            Components = new List<IGameComponent>();
            IsPaused = false;            

            Randomizer = new Random(DateTime.Now.Second * DateTime.Now.Minute);

            TargetElapsedTime = TimeSpan.FromSeconds(1 / 30.0);
            DiagnosticsLocation = new PointF(20, 20);
            DiagnosticsFontColor = Color.Black;
        }

        private T[] GetEnumValues<T>()
        {
            if (!typeof(T).IsEnum)
                return null;

            FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
            T[] values = new T[fields.Length];

            for (int i = 0; i < fields.Length; i++)
            {
                values[i] = (T)fields[i].GetValue(null);
            }

            return values;
        }

        #region XNA Override Methods
        protected override void LoadContent()
        {
            DefaultFont = ContentManager.GetFont("Default");
            InputManager.SoftMenuFont = DefaultFont;

            Game.LoadContent();
            Game.CreateMenus();

            foreach (var component in Components)
                component.LoadContent(ContentManager);

            base.LoadContent();
        }        

        protected override void BeginRun()
        {
            Game.BeginRun();
            base.BeginRun();
        }

        protected override void Draw(Microsoft.Xna.Framework.GameTime gameTime)
        {
            Game.Draw(gameTime.GetWiMoGameTime());
            InputManager.Draw(gameTime.GetWiMoGameTime());

            foreach (var component in Components)
                component.Draw(gameTime.GetWiMoGameTime());

            if(EnableDiagnostics)
                Display.DrawText(DiagnosticsLocation, string.Format("FPS: {0}", 1000/gameTime.ElapsedGameTime.Milliseconds), DefaultFont, DiagnosticsFontColor);

            Display.Render();

            base.Draw(gameTime);
        }

        protected override void Update(Microsoft.Xna.Framework.GameTime gameTime)
        {
            GameTime wimoGameTime = gameTime.GetWiMoGameTime();

            if (!IsPaused)
            {
                PhysicsManager.Update(wimoGameTime);
                CollisionManager.Update(wimoGameTime);
            }

            foreach(var component in Components)
                component.Update(wimoGameTime);

            InputManager.Update();

            Game.Update(wimoGameTime);

            base.Update(gameTime);
        }


        protected override void Initialize()
        {
            Game.Initialize();

            foreach (var component in Components)
                component.Initialize();

            base.Initialize();
        }
        #endregion

        public void StartHopper()
        {

        }

        public void StopHopper()
        {

        }


        public void Initialize(IGame game)
        {
            Game = game;
        }

        public void Start()
        {
           // base.Run();
        }

        public new void Exit()
        {
            base.Exit();
        }

        public void Pause()
        {
            IsPaused = true;   
        }

        public void Resume()
        {
            IsPaused = false;
        }

        public void RegisterComponent(IGameComponent component)
        {
            component.InputManager = InputManager;
            component.Display = Display;
            component.Engine = this;
            Components.Add(component);
        }

        public void OnResize(Size bounds)
        {
            throw new NotImplementedException();
        }

        
        public void Vibrate(int ms)
        {
            
        }

        public void BeginVibrate()
        {
            
        }

        public void EndVibrate()
        {
            
        }
    }
}
